(load "prelude.ss")

(define (sweet-toothL x)
  (set! last x)
  (list x 'cake))

(define last 'angelfood)
(define ingredients '())

(define (sweet-toothR food)
  (set! ingredients (cons food ingredients))
  (list food 'cake))


(define (deep m)
  (if (zero? m)
    'pizza
    (cons (deepM ;;previous version was deep
                 (sub1 m))
          '())))

(define Ns '())
(define Rs '())

(define (deepR n)
  (let ((result (deep n)))
   (set! Rs (cons (deep n) Rs))
   (set! Ns (cons n Ns))
   result))

(define (find n Ns Rs)
  (letrec ((A (lambda (ns rs)
                (cond
                  ((null? ns) #f)
                  ((= (car ns) n) (car rs))
                  (else (A (cdr ns) (cdr rs)))))))
    (A Ns Rs)))

;; (define deepM
;;   (let ((Rs '())
;;         (Ns '()))
;;     (lambda (n)
;;       (if (member? n Ns)
;;         (find n Ns Rs)
;;         (let ((result (deep n)))
;;          (set! Rs (cons result Rs))
;;          (set! Ns (cons n Ns))
;;          result)))))

;; Page 118
(define deepM
  (let ((Rs '())
        (Ns '()))
    (lambda (n)
      (let ((exists (find n Ns Rs)))
        (if (atom? exists) ;; True on not found
          (let ((result (deep n)))
            (set! Rs (cons result Rs))
            (set! Ns (cons n Ns))
            result)
          exists)))))

;; Page 119
;(define length
;  (let ((h (lambda (l) 0)))
;   (set! h
;     (lambda (l)
;       (cond ((null? l) 0)
;             (else (+ 1 (h (cdr l)))))))
;   h))

;; Page 121
(define (L length)
  (lambda (l)
    ;;(display "calling me...\n")
    (cond ((null? l) 0)
          (else (add1 (length (cdr l)))))))

;; Page 119
(define length
  (let ((h (lambda (l) 0)))
   (set! h
     #|
     The argument for L has to be (lambda (arg) (h arg))
     A simple h won't work.
     |#
     (L (lambda (arg) (h arg))))
   h))

;; Page 123
(define (Y! L)
  (let ((h (lambda (l) '())))
   (set! h (L (lambda (arg) (h arg))))
   h))
(define (Y-bang f)
  (letrec ((h (f (lambda (arg) (h arg)))))
    h))

;; Page 124
(define biz
  (let ((x 0))
   (lambda (f)
     (set! x (add1 x))
     (lambda (a)
       (display "a = ")
       (display a)
       (display "; x = ")
       (display x)
       (newline)
       (if (= a x)
           0
           (f a))))))
